{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ad7b0c91",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "#  28\\.  层次聚类应用及聚类树绘制  # \n",
    "\n",
    "##  28.1.  介绍  # \n",
    "\n",
    "本次挑战将针对小麦种子数据集进行层次聚类，并绘制层次聚类二叉树图像。 \n",
    "\n",
    "##  28.2.  知识点  # \n",
    "\n",
    "  * 层次聚类 \n",
    "\n",
    "  * 修剪层次聚类二叉树 \n",
    "\n",
    "##  28.3.  数据集介绍  # \n",
    "\n",
    "本次挑战将用的小麦种子数据集，该数据集由若干小麦种子的几何参数组成，共包含有 7 个维度。这些维度有：种子面积、种子周长、种子致密度、核仁长度、核仁宽度、种子不对称系数、核沟长度。 \n",
    "\n",
    "你可以加载预览该数据集： "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7b2c840",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "outputs": [],
   "source": [
    "wget -nc https://cdn.aibydoing.com/aibydoing/files/challenge-8-seeds.csv"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ca6696f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.read_csv(\"challenge-8-seeds.csv\")\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7fa6a6c3",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "|  f1  |  f2  |  f3  |  f4  |  f5  |  f6  |  f7   \n",
    "---|---|---|---|---|---|---|---  \n",
    "0  |  15.26  |  14.84  |  0.8710  |  5.763  |  3.312  |  2.221  |  5.220   \n",
    "1  |  14.88  |  14.57  |  0.8811  |  5.554  |  3.333  |  1.018  |  4.956   \n",
    "2  |  14.29  |  14.09  |  0.9050  |  5.291  |  3.337  |  2.699  |  4.825   \n",
    "3  |  13.84  |  13.94  |  0.8955  |  5.324  |  3.379  |  2.259  |  4.805   \n",
    "4  |  16.14  |  14.99  |  0.9034  |  5.658  |  3.562  |  1.355  |  5.175   \n",
    "  \n",
    "可以看到，数据集从 f1-f7 代表 7 种特征。下面，我就要通过层次聚类方法完成对该种子数据集的聚类，从而估计出数据集到底采集了几种类别的小麦种子。 \n",
    "\n",
    "##  28.4.  层次聚类  # \n",
    "\n",
    "前面的实验中，我们学习了如何实现一个自底向上的层次聚类算法，并了解通过 scikit-learn 完成层次聚类。这次的挑战中，我们将尝试通过 SciPy 完成，SciPy 作为知名的科学计算模块也同样提供了层次聚类的方法。 \n",
    "\n",
    "Exercise 28.1 \n",
    "\n",
    "挑战：使用 SciPy 中的 Agglomerative 聚类方法完成小麦种子层次聚类。 \n",
    "\n",
    "规定：使用 ` ward  ` 离差平方和法度量相似度，距离计算使用欧式距离。 \n",
    "\n",
    "提示：SciPy 中的 Agglomerative 聚类方法类为 ` scipy.cluster.hierarchy.linkage()  ` 。 [ 阅读官方文档 ](https://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.linkage.html#scipy.cluster.hierarchy.linkage)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee992d69",
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.cluster import hierarchy\n",
    "\n",
    "## 代码开始 ### (≈ 1 行代码)\n",
    "Z = None\n",
    "## 代码结束 ###"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c502a04f",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 28.1 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8977e354",
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.cluster import hierarchy\n",
    "\n",
    "### 代码开始 ### (≈ 1 行代码)\n",
    "Z = hierarchy.linkage(df, method ='ward', metric='euclidean')\n",
    "### 代码结束 ###"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c87d7900",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "运行测试 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea692035",
   "metadata": {},
   "outputs": [],
   "source": [
    "Z[:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9aa2506f",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "期望输出 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "591ca908",
   "metadata": {},
   "outputs": [],
   "source": [
    "array([[1.72000000e+02, 2.06000000e+02, 1.17378192e-01, 2.00000000e+00],\n",
    "       [1.48000000e+02, 1.98000000e+02, 1.33858134e-01, 2.00000000e+00],\n",
    "       [1.22000000e+02, 1.33000000e+02, 1.35824740e-01, 2.00000000e+00],\n",
    "       [7.00000000e+00, 2.80000000e+01, 1.79010642e-01, 2.00000000e+00],\n",
    "       [1.37000000e+02, 1.38000000e+02, 1.91444744e-01, 2.00000000e+00]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a25ef87c",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "你会发现，SciPy 中的 linkage 方法会返回一个 Nx4 的矩阵（上面的期望输出为前 5 行）。该矩阵其实包含了每一步合并类别的信息，以第一行举例： \n",
    "\n",
    "` [1.72000000e+02,  2.06000000e+02,  1.17378192e-01,  2.00000000e+00]  ` 表示 172 类别和 206 类别被合并，当前距离为 ` 1.17378192e-01  ` 属于全集合最短距离，合并后类别中包含有 2 个数据样本。 \n",
    "\n",
    "也就是说 SciPy 把整个层次聚类的过程都呈现出来了，这一点对于理解层次聚类是非常有帮助的。除此之外，SciPy 还集成了一个绘制层次聚类二叉树的方法 ` dendrogram  ` 。接下来，就尝试使用它来绘制出上面聚类的层次树。 \n",
    "\n",
    "Exercise 28.2 \n",
    "\n",
    "挑战：使用 SciPy 中的 dendrogram 方法绘制小麦种子层次聚类二叉树。 \n",
    "\n",
    "提示：SciPy 中绘制层次聚类二叉树的方法为 ` scipy.cluster.hierarchy.dendrogram()  ` 。 [ 阅读官方文档 ](https://docs.scipy.org/doc/scipy/reference/generated/scipy.cluster.hierarchy.dendrogram.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e68706c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "plt.figure(figsize=(15, 8))\n",
    "## 代码开始 ### (≈ 1 行代码)\n",
    "\n",
    "## 代码结束 ###\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b3da49f",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 28.2 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9cf9106b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "plt.figure(figsize=(15, 8))\n",
    "### 代码开始 ### (≈ 1 行代码)\n",
    "hierarchy.dendrogram(Z)\n",
    "### 代码结束 ###\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b328f20",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "期望输出 \n",
    "\n",
    "![image](https://cdn.aibydoing.com/aibydoing/images/document-uid214893labid6102timestamp1531806113660.png)\n",
    "\n",
    "层次聚类二叉树中，  $x$  轴代表数据点原类别，也就是样本序号，而  $y$  轴表示类别之间的距离。 \n",
    "\n",
    "特别地，图中的横线所在高度表明类别间合并时的距离。如果相邻两横线的间距越大，则说明前序类别在合并时的距离越远，也就表明可能并不属于一类不需要被合并。 \n",
    "\n",
    "上图中蓝色线所对应的  $y$  差值最大，即说明红色和绿色两个分支很有可能不属于一类。 \n",
    "\n",
    "##  28.5.  修剪层次聚类二叉树  # \n",
    "\n",
    "上面，我们使用 ` dendrogram()  ` 来绘制二叉树。你会发现当样本数量越多时，叶节点就越密集，最终导致通过二叉树辨识不同类别的可视性降低。 \n",
    "\n",
    "其实，你可以指定多个参数来修剪完整的二叉树结果，让其具备更好地观赏性。 \n",
    "\n",
    "Exercise 28.3 \n",
    "\n",
    "挑战：对小麦种子层次聚类二叉树进行修剪。 \n",
    "\n",
    "提示：修改参数 ` truncate_mode  ` , ` p  ` , ` show_leaf_counts  ` , ` show_contracted  ` 。 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b9d99e6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(15, 8))\n",
    "## 代码开始 ### (≈ 1 行代码)\n",
    "\n",
    "## 代码结束 ###\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce9b2f34",
   "metadata": {
    "lines_to_next_cell": 0
   },
   "source": [
    "参考答案  Exercise 28.3 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8e047c30",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(15, 8))\n",
    "### 代码开始 ### (≈ 1 行代码)\n",
    "hierarchy.dendrogram(Z, truncate_mode='lastp', p=15, show_leaf_counts=True, show_contracted=True)\n",
    "### 代码结束 ###\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "602a6988",
   "metadata": {},
   "source": [
    "期望输出 \n",
    "\n",
    "![image](https://cdn.aibydoing.com/aibydoing/images/document-uid214893labid6102timestamp1531806114000.png)\n",
    "\n",
    "此时的二叉树看起来就更美观了。那么，本次挑战中到底判定小麦种子大致为几类呢？下面通过层次聚类二叉树给出建议： \n",
    "\n",
    "[ ![https://cdn.aibydoing.com/aibydoing/images/document-uid214893labid6102timestamp1531806114224.png](https://cdn.aibydoing.com/aibydoing/images/document-uid214893labid6102timestamp1531806114224.png) ](https://cdn.aibydoing.com/aibydoing/images/document-uid214893labid6102timestamp1531806114224.png)\n",
    "\n",
    "所以，最终建议将小麦种子数据集划为 3 类，也就是其中包含 3 种不同品种的小麦籽粒。 "
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
